home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 39 / Amiga Format CD39 (1999-04-13)(Future Publishing)(GB)[!][issue 1999-05].iso / -seriously_amiga- / graphics / ripley / source / store.c < prev    next >
C/C++ Source or Header  |  1999-03-02  |  15KB  |  581 lines

  1. /* store.c, picture output routines                                         */
  2.  
  3. /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
  4.  
  5. /*
  6.  * Disclaimer of Warranty
  7.  *
  8.  * These software programs are available to the user without any license fee or
  9.  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
  10.  * any and all warranties, whether express, implied, or statuary, including any
  11.  * implied warranties or merchantability or of fitness for a particular
  12.  * purpose.  In no event shall the copyright-holder be liable for any
  13.  * incidental, punitive, or consequential damages of any kind whatsoever
  14.  * arising from the use of these programs.
  15.  *
  16.  * This disclaimer of warranty extends to the user of these programs and user's
  17.  * customers, employees, agents, transferees, successors, and assigns.
  18.  *
  19.  * The MPEG Software Simulation Group does not represent or warrant that the
  20.  * programs furnished hereunder are free of infringement of any third-party
  21.  * patents.
  22.  *
  23.  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
  24.  * are subject to royalty fees to patent holders.  Many of these patents are
  25.  * general enough such that they are unavoidable regardless of implementation
  26.  * design.
  27.  *
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <fcntl.h>
  34.  
  35. #include "config.h"
  36. #include "global.h"
  37.  
  38. /* private prototypes */
  39. static void store_one _ANSI_ARGS_((char *outname, unsigned char *src[],
  40.   int offset, int incr, int height));
  41. static void store_yuv _ANSI_ARGS_((char *outname, unsigned char *src[],
  42.   int offset, int incr, int height));
  43. static void store_sif _ANSI_ARGS_((char *outname, unsigned char *src[],
  44.   int offset, int incr, int height));
  45. static void store_ppm_tga _ANSI_ARGS_((char *outname, unsigned char *src[],
  46.   int offset, int incr, int height, int tgaflag));
  47. static void store_yuv1 _ANSI_ARGS_((char *name, unsigned char *src,
  48.   int offset, int incr, int width, int height));
  49. static void putbyte _ANSI_ARGS_((int c));
  50. static void putword _ANSI_ARGS_((int w));
  51. static void conv422to444 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
  52. static void conv420to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
  53.  
  54. #define OBFRSIZE 4096
  55. static unsigned char obfr[OBFRSIZE];
  56. static unsigned char *optr;
  57. static int outfile;
  58.  
  59. /*
  60.  * store a picture as either one frame or two fields
  61.  */
  62. void Write_Frame(src,frame)
  63. unsigned char *src[];
  64. int frame;
  65. {
  66.   char outname[FILENAME_LENGTH];
  67.  
  68.   if (progressive_sequence || progressive_frame || Frame_Store_Flag)
  69.   {
  70.     /* progressive */
  71.     sprintf(outname,Output_Picture_Filename,frame,'f');
  72.     store_one(outname,src,0,Coded_Picture_Width,vertical_size);
  73.   }
  74.   else
  75.   {
  76.     /* interlaced */
  77.     sprintf(outname,Output_Picture_Filename,frame,'a');
  78.     store_one(outname,src,0,Coded_Picture_Width<<1,vertical_size>>1);
  79.  
  80.     if (!doneFlag)
  81.     {
  82.     sprintf(outname,Output_Picture_Filename,frame,'b');
  83.     store_one(outname,src,
  84.       Coded_Picture_Width,Coded_Picture_Width<<1,vertical_size>>1);
  85.     }
  86.   }
  87. }
  88.  
  89. /*
  90.  * store one frame or one field
  91.  */
  92. static void store_one(outname,src,offset,incr,height)
  93. char *outname;
  94. unsigned char *src[];
  95. int offset, incr, height;
  96. {
  97.   switch (Output_Type)
  98.   {
  99.   case T_YUV:
  100.     store_yuv(outname,src,offset,incr,height);
  101.     break;
  102.   case T_SIF:
  103.     store_sif(outname,src,offset,incr,height);
  104.     break;
  105.   case T_TGA:
  106.     store_ppm_tga(outname,src,offset,incr,height,1);
  107.     break;
  108.   case T_PPM:
  109.     store_ppm_tga(outname,src,offset,incr,height,0);
  110.     break;
  111. #ifdef DISPLAY
  112.   case T_X11:
  113.     Display_Image(src);
  114.     break;
  115. #endif
  116.   default:
  117.     break;
  118.   }
  119. }
  120.  
  121. /* separate headerless files for y, u and v */
  122. static void store_yuv(outname,src,offset,incr,height)
  123. char *outname;
  124. unsigned char *src[];
  125. int offset,incr,height;
  126. {
  127.   int hsize;
  128.   char tmpname[FILENAME_LENGTH];
  129.  
  130.   hsize = horizontal_size;
  131.  
  132.   sprintf(tmpname,"%s.Y",outname);
  133.   store_yuv1(tmpname,src[0],offset,incr,hsize,height);
  134.  
  135.   if (chroma_format!=CHROMA444)
  136.   {
  137.     offset>>=1; incr>>=1; hsize>>=1;
  138.   }
  139.  
  140.   if (chroma_format==CHROMA420)
  141.   {
  142.     height>>=1;
  143.   }
  144.  
  145.   sprintf(tmpname,"%s.U",outname);
  146.   store_yuv1(tmpname,src[1],offset,incr,hsize,height);
  147.  
  148.   sprintf(tmpname,"%s.V",outname);
  149.   store_yuv1(tmpname,src[2],offset,incr,hsize,height);
  150. }
  151.  
  152. /* auxiliary routine */
  153. static void store_yuv1(name,src,offset,incr,width,height)
  154. char *name;
  155. unsigned char *src;
  156. int offset,incr,width,height;
  157. {
  158.   int i, j;
  159.   unsigned char *p;
  160.  
  161.   if (!Quiet_Flag)
  162.     fprintf(stderr,"saving %s\n",name);
  163.  
  164.   if ((outfile = open(name,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
  165.   {
  166.     sprintf(Error_Text,"Couldn't create %s\n",name);
  167.     Error(Error_Text);
  168.   }
  169.  
  170.   optr=obfr;
  171.  
  172.   for (i=0; i<height; i++)
  173.   {
  174.     p = src + offset + incr*i;
  175.     for (j=0; j<width; j++)
  176.       putbyte(*p++);
  177.   }
  178.  
  179.   if (optr!=obfr)
  180.     write(outfile,obfr,optr-obfr);
  181.  
  182.   close(outfile);
  183. }
  184.  
  185. /*
  186.  * store as headerless file in U,Y,V,Y format
  187.  */
  188. static void store_sif (outname,src,offset,incr,height)
  189. char *outname;
  190. unsigned char *src[];
  191. int offset, incr, height;
  192. {
  193.   int i,j;
  194.   unsigned char *py, *pu, *pv;
  195.   static unsigned char *u422, *v422;
  196.  
  197.   if (chroma_format==CHROMA444)
  198.     Error("4:4:4 not supported for SIF format");
  199.  
  200.   if (chroma_format==CHROMA422)
  201.   {
  202.     u422 = src[1];
  203.     v422 = src[2];
  204.   }
  205.   else
  206.   {
  207.     if (!u422)
  208.     {
  209.       if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
  210.                                            *Coded_Picture_Height)))
  211.         Error("malloc failed");
  212.       if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
  213.                                            *Coded_Picture_Height)))
  214.         Error("malloc failed");
  215.     }
  216.   
  217.     conv420to422(src[1],u422);
  218.     conv420to422(src[2],v422);
  219.   }
  220.  
  221.   strcat(outname,".SIF");
  222.  
  223.   if (!Quiet_Flag)
  224.     fprintf(stderr,"saving %s\n",outname);
  225.  
  226.   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
  227.   {
  228.     sprintf(Error_Text,"Couldn't create %s\n",outname);
  229.     Error(Error_Text);
  230.   }
  231.  
  232.   optr = obfr;
  233.  
  234.   for (i=0; i<height; i++)
  235.   {
  236.     py = src[0] + offset + incr*i;
  237.     pu = u422 + (offset>>1) + (incr>>1)*i;
  238.     pv = v422 + (offset>>1) + (incr>>1)*i;
  239.  
  240.     for (j=0; j<horizontal_size; j+=2)
  241.     {
  242.       putbyte(*pu++);
  243.       putbyte(*py++);
  244.       putbyte(*pv++);
  245.       putbyte(*py++);
  246.     }
  247.   }
  248.  
  249.   if (optr!=obfr)
  250.     write(outfile,obfr,optr-obfr);
  251.  
  252.   close(outfile);
  253. }
  254.  
  255. /*
  256.  * store as PPM (PBMPLUS) or uncompressed Truevision TGA ('Targa') file
  257.  */
  258. static void store_ppm_tga(outname,src,offset,incr,height,tgaflag)
  259. char *outname;
  260. unsigned char *src[];
  261. int offset, incr, height;
  262. int tgaflag;
  263. {
  264.   int i, j;
  265.   int y, u, v, r, g, b;
  266.   int crv, cbu, cgu, cgv;
  267.   unsigned char *py, *pu, *pv;
  268.   static unsigned char tga24[14] = {0,0,2,0,0,0,0, 0,0,0,0,0,24,32};
  269.   char header[FILENAME_LENGTH];
  270.   static unsigned char *u422, *v422, *u444, *v444;
  271.  
  272.   if (chroma_format==CHROMA444)
  273.   {
  274.     u444 = src[1];
  275.     v444 = src[2];
  276.   }
  277.   else
  278.   {
  279.     if (!u444)
  280.     {
  281.       if (chroma_format==CHROMA420)
  282.       {
  283.         if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
  284.                                              *Coded_Picture_Height)))
  285.           Error("malloc failed");
  286.         if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
  287.                                              *Coded_Picture_Height)))
  288.           Error("malloc failed");
  289.       }
  290.  
  291.       if (!(u444 = (unsigned char *)malloc(Coded_Picture_Width
  292.                                            *Coded_Picture_Height)))
  293.         Error("malloc failed");
  294.  
  295.       if (!(v444 = (unsigned char *)malloc(Coded_Picture_Width
  296.                                            *Coded_Picture_Height)))
  297.         Error("malloc failed");
  298.     }
  299.  
  300.     if (chroma_format==CHROMA420)
  301.     {
  302.       conv420to422(src[1],u422);
  303.       conv420to422(src[2],v422);
  304.       conv422to444(u422,u444);
  305.       conv422to444(v422,v444);
  306.     }
  307.     else
  308.     {
  309.       conv422to444(src[1],u444);
  310.       conv422to444(src[2],v444);
  311.     }
  312.   }
  313.  
  314.   strcat(outname,tgaflag ? ".tga" : ".ppm");
  315.  
  316.   if (!Quiet_Flag)
  317.     fprintf(stderr,"saving %s\n",outname);
  318.  
  319.   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
  320.   {
  321.     sprintf(Error_Text,"Couldn't create %s\n",outname);
  322.     Error(Error_Text);
  323.   }
  324.  
  325.   optr = obfr;
  326.  
  327.   if (tgaflag)
  328.   {
  329.     /* TGA header */
  330.     for (i=0; i<12; i++)
  331.       putbyte(tga24[i]);
  332.  
  333.     putword(horizontal_size); putword(height);
  334.     putbyte(tga24[12]); putbyte(tga24[13]);
  335.   }
  336.   else
  337.   {
  338.     /* PPM header */
  339.     sprintf(header,"P6\n%d %d\n255\n",horizontal_size,height);
  340.  
  341.     for (i=0; header[i]!=0; i++)
  342.       putbyte(header[i]);
  343.   }
  344.  
  345.   /* matrix coefficients */
  346.   crv = Inverse_Table_6_9[matrix_coefficients][0];
  347.   cbu = Inverse_Table_6_9[matrix_coefficients][1];
  348.   cgu = Inverse_Table_6_9[matrix_coefficients][2];
  349.   cgv = Inverse_Table_6_9[matrix_coefficients][3];
  350.   
  351.   for (i=0; i<height; i++)
  352.   {
  353.     py = src[0] + offset + incr*i;
  354.     pu = u444 + offset + incr*i;
  355.     pv = v444 + offset + incr*i;
  356.  
  357.     for (j=0; j<horizontal_size; j++)
  358.     {
  359.       u = *pu++ - 128;
  360.       v = *pv++ - 128;
  361.       y = 76309 * (*py++ - 16); /* (255/219)*65536 */
  362.       r = Clip[(y + crv*v + 32768)>>16];
  363.       g = Clip[(y - cgu*u - cgv*v + 32768)>>16];
  364.       b = Clip[(y + cbu*u + 32786)>>16];
  365.  
  366.       if (tgaflag)
  367.       {
  368.         putbyte(b); putbyte(g); putbyte(r);
  369.       }
  370.       else
  371.       {
  372.         putbyte(r); putbyte(g); putbyte(b);
  373.       }
  374.     }
  375.   }
  376.  
  377.   if (optr!=obfr)
  378.     write(outfile,obfr,optr-obfr);
  379.  
  380.   close(outfile);
  381. }
  382.  
  383. static void putbyte(c)
  384. int c;
  385. {
  386.   *optr++ = c;
  387.  
  388.   if (optr == obfr+OBFRSIZE)
  389.   {
  390.     write(outfile,obfr,OBFRSIZE);
  391.     optr = obfr;
  392.   }
  393. }
  394.  
  395. static void putword(w)
  396. int w;
  397. {
  398.   putbyte(w); putbyte(w>>8);
  399. }
  400.  
  401. /* horizontal 1:2 interpolation filter */
  402. static void conv422to444(src,dst)
  403. unsigned char *src,*dst;
  404. {
  405.   int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3;
  406.  
  407.   w = Coded_Picture_Width>>1;
  408.  
  409.   if (base.MPEG2_Flag)
  410.   {
  411.     for (j=0; j<Coded_Picture_Height; j++)
  412.     {
  413.       for (i=0; i<w; i++)
  414.       {
  415.         i2 = i<<1;
  416.         im2 = (i<2) ? 0 : i-2;
  417.         im1 = (i<1) ? 0 : i-1;
  418.         ip1 = (i<w-1) ? i+1 : w-1;
  419.         ip2 = (i<w-2) ? i+2 : w-1;
  420.         ip3 = (i<w-3) ? i+3 : w-1;
  421.  
  422.         /* FIR filter coefficients (*256): 21 0 -52 0 159 256 159 0 -52 0 21 */
  423.         /* even samples (0 0 256 0 0) */
  424.         dst[i2] = src[i];
  425.  
  426.         /* odd samples (21 -52 159 159 -52 21) */
  427.         dst[i2+1] = Clip[(int)(21*(src[im2]+src[ip3])
  428.                         -52*(src[im1]+src[ip2]) 
  429.                        +159*(src[i]+src[ip1])+128)>>8];
  430.       }
  431.       src+= w;
  432.       dst+= Coded_Picture_Width;
  433.     }
  434.   }
  435.   else
  436.   {
  437.     for (j=0; j<Coded_Picture_Height; j++)
  438.     {
  439.       for (i=0; i<w; i++)
  440.       {
  441.  
  442.         i2 = i<<1;
  443.         im3 = (i<3) ? 0 : i-3;
  444.         im2 = (i<2) ? 0 : i-2;
  445.         im1 = (i<1) ? 0 : i-1;
  446.         ip1 = (i<w-1) ? i+1 : w-1;
  447.         ip2 = (i<w-2) ? i+2 : w-1;
  448.         ip3 = (i<w-3) ? i+3 : w-1;
  449.  
  450.         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
  451.         dst[i2] =   Clip[(int)(  5*src[im3]
  452.                          -21*src[im2]
  453.                          +70*src[im1]
  454.                         +228*src[i]
  455.                          -37*src[ip1]
  456.                          +11*src[ip2]+128)>>8];
  457.  
  458.        dst[i2+1] = Clip[(int)(  5*src[ip3]
  459.                          -21*src[ip2]
  460.                          +70*src[ip1]
  461.                         +228*src[i]
  462.                          -37*src[im1]
  463.                          +11*src[im2]+128)>>8];
  464.       }
  465.       src+= w;
  466.       dst+= Coded_Picture_Width;
  467.     }
  468.   }
  469. }
  470.  
  471. /* vertical 1:2 interpolation filter */
  472. static void conv420to422(src,dst)
  473. unsigned char *src,*dst;
  474. {
  475.   int w, h, i, j, j2;
  476.   int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7;
  477.  
  478.   w = Coded_Picture_Width>>1;
  479.   h = Coded_Picture_Height>>1;
  480.  
  481.   if (progressive_frame)
  482.   {
  483.     /* intra frame */
  484.     for (i=0; i<w; i++)
  485.     {
  486.       for (j=0; j<h; j++)
  487.       {
  488.         j2 = j<<1;
  489.         jm3 = (j<3) ? 0 : j-3;
  490.         jm2 = (j<2) ? 0 : j-2;
  491.         jm1 = (j<1) ? 0 : j-1;
  492.         jp1 = (j<h-1) ? j+1 : h-1;
  493.         jp2 = (j<h-2) ? j+2 : h-1;
  494.         jp3 = (j<h-3) ? j+3 : h-1;
  495.  
  496.         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
  497.         /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */
  498.         dst[w*j2] =     Clip[(int)(  3*src[w*jm3]
  499.                              -16*src[w*jm2]
  500.                              +67*src[w*jm1]
  501.                             +227*src[w*j]
  502.                              -32*src[w*jp1]
  503.                              +7*src[w*jp2]+128)>>8];
  504.  
  505.         dst[w*(j2+1)] = Clip[(int)(  3*src[w*jp3]
  506.                              -16*src[w*jp2]
  507.                              +67*src[w*jp1]
  508.                             +227*src[w*j]
  509.                              -32*src[w*jm1]
  510.                              +7*src[w*jm2]+128)>>8];
  511.       }
  512.       src++;
  513.       dst++;
  514.     }
  515.   }
  516.   else
  517.   {
  518.     /* intra field */
  519.     for (i=0; i<w; i++)
  520.     {
  521.       for (j=0; j<h; j+=2)
  522.       {
  523.         j2 = j<<1;
  524.  
  525.         /* top field */
  526.         jm6 = (j<6) ? 0 : j-6;
  527.         jm4 = (j<4) ? 0 : j-4;
  528.         jm2 = (j<2) ? 0 : j-2;
  529.         jp2 = (j<h-2) ? j+2 : h-2;
  530.         jp4 = (j<h-4) ? j+4 : h-2;
  531.         jp6 = (j<h-6) ? j+6 : h-2;
  532.  
  533.         /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */
  534.         /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */
  535.         dst[w*j2] = Clip[(int)(  1*src[w*jm6]
  536.                          -7*src[w*jm4]
  537.                          +30*src[w*jm2]
  538.                         +248*src[w*j]
  539.                          -21*src[w*jp2]
  540.                           +5*src[w*jp4]+128)>>8];
  541.  
  542.         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
  543.         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
  544.         dst[w*(j2+2)] = Clip[(int)( 7*src[w*jm4]
  545.                              -35*src[w*jm2]
  546.                             +194*src[w*j]
  547.                             +110*src[w*jp2]
  548.                              -24*src[w*jp4]
  549.                               +4*src[w*jp6]+128)>>8];
  550.  
  551.         /* bottom field */
  552.         jm5 = (j<5) ? 1 : j-5;
  553.         jm3 = (j<3) ? 1 : j-3;
  554.         jm1 = (j<1) ? 1 : j-1;
  555.         jp1 = (j<h-1) ? j+1 : h-1;
  556.         jp3 = (j<h-3) ? j+3 : h-1;
  557.         jp5 = (j<h-5) ? j+5 : h-1;
  558.         jp7 = (j<h-7) ? j+7 : h-1;
  559.  
  560.         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
  561.         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
  562.         dst[w*(j2+1)] = Clip[(int)( 7*src[w*jp5]
  563.                              -35*src[w*jp3]
  564.                             +194*src[w*jp1]
  565.                             +110*src[w*jm1]
  566.                              -24*src[w*jm3]
  567.                               +4*src[w*jm5]+128)>>8];
  568.  
  569.         dst[w*(j2+3)] = Clip[(int)(  1*src[w*jp7]
  570.                              -7*src[w*jp5]
  571.                              +30*src[w*jp3]
  572.                             +248*src[w*jp1]
  573.                              -21*src[w*jm1]
  574.                               +5*src[w*jm3]+128)>>8];
  575.       }
  576.       src++;
  577.       dst++;
  578.     }
  579.   }
  580. }
  581.